import hashlib
from datetime import datetime
from typing import Tuple, Any, Union

from sqlalchemy import and_

from app.utils import random_uuid_string
from app.models.data_base_models import User
from app.services import get_base_session as get_session


class UserService:

    @staticmethod
    def get_all_users() -> Tuple[bool, Union[list[User], str, None]]:
        session = get_session()
        try:
            users = session.query(User).all()
            if users is None or len(users) == 0:
                users = []
            return True, users
        except Exception as e:
            return False, str(e)
        finally:
            session.close()

    @staticmethod
    def search_users(userName: Union[str, None] = None, personName: Union[str, None] = None) -> Tuple[
        bool, Union[list[User], str, None]]:
        conditions = []
        if userName is not None and isinstance(userName, str) and len(userName) > 0:
            conditions.append(User.user_name.like('%' + userName + '%'))
        if personName is not None and isinstance(personName, str) and len(personName) > 0:
            conditions.append(User.person_name == personName)
        if len(conditions) > 0:
            session = get_session()
            try:
                users = session.query(User).filter(and_(*conditions)).all()
                if users is None or len(users) == 0:
                    users = []
                return True, users
            except Exception as e:
                return False, str(e)
            finally:
                session.close()
        else:
            return UserService.get_all_users()

    @staticmethod
    def check_login(username: str, password: str) -> Tuple[bool, str, Union[User, None]]:
        session = get_session()
        try:
            user = session.query(User).filter(User.user_name == username).first()
            if user is None:
                return False, "user is not exist", None
            salted_password = str(hashlib.pbkdf2_hmac(
                'sha512', password.encode('utf-8'), user.salt.encode('utf-8'), 100000).hex())
            if salted_password == user.salted_password:
                return True, "success", user
            return False, "invalid password", None
        except Exception as e:
            return False, str(e), None
        finally:
            session.close()


    @staticmethod
    def reset_password_by_id(userId: int, oldPassword: str, newPassword: str) -> Tuple[bool, str]:
        session = get_session()
        try:
            user = session.query(User).filter(User.id == userId).first()
            if user is None:
                return False, "用户不存在"
            salted_password = str(hashlib.pbkdf2_hmac(
                'sha512', oldPassword.encode('utf-8'), user.salt.encode('utf-8'), 100000).hex())
            if salted_password != user.salted_password:
                return False, "密码输入错误"
            user.salted_password = str(hashlib.pbkdf2_hmac(
                'sha512', newPassword.encode('utf-8'), user.salt.encode('utf-8'), 100000).hex())
            session.commit()
            return True, "修改成功"
        except Exception as e:
            return False, str(e)




    @staticmethod
    def get_user_by_id(user_id: int) -> Tuple[bool, str, Union[User, None]]:
        session = get_session()
        try:
            user = session.query(User).filter(User.id == user_id).first()
            if user is None:
                return False, "user is not exist", None
            return True, "success", user
        except Exception as e:
            return False, str(e), None
        finally:
            session.close()

    @staticmethod
    def register_user(username: str, password: str, roleType: int, personname: str, views: str) -> Tuple[bool, str]:
        session = get_session()
        try:
            user = session.query(User).filter(User.user_name == username).first()
            if user is not None:
                return False, "Username is already exist"
            salt = random_uuid_string()
            salted_password = str(hashlib.pbkdf2_hmac(
                'sha512', password.encode('utf-8'), salt.encode('utf-8'), 100000).hex())
            user = User(
                user_name=username,
                person_name=personname,
                salt=salt,
                salted_password=salted_password,
                role_type=roleType,
                upload_time=datetime.now(),
                create_time=datetime.now(),
                views=views
            )
            session.add(user)
            session.commit()
            session.close()
            return True, "succeed to register"
        except Exception as e:
            return False, str(e)
        finally:
            session.close()

    @staticmethod
    def delete_user(userId: int) -> Tuple[bool, str]:
        session = get_session()
        try:
            user = session.query(User).filter(User.id == userId).first()
            if user is None:
                return True, "用户不存在"
            session.delete(user)
            session.commit()
            session.close()
            return True, "用户已删除"
        except Exception as e:
            return False, str(e)
        finally:
            session.close()

    @staticmethod
    def set_password(userId: str, password: str) -> Tuple[bool, str]:
        session = get_session()
        try:
            user = session.query(User).filter(User.user_id == userId).first()
            if user is None:
                return False, "用户不存在"
            user.salted_password = str(hashlib.pbkdf2_hmac(
                'sha512', password.encode('utf-8'), user.salt.encode('utf-8'), 100000).hex())
            session.commit()
            return True, "succeed to set view"
        except Exception as e:
            return False, str(e)
        finally:
            session.close()


    @staticmethod
    def set_user_by_id(user_id, data: dict[str, Any]) -> Tuple[bool, str]:
        session = get_session()
        try:
            user = session.query(User).filter(User.id == user_id).first()
            if user is None:
                return False, "the user does not exist"
            views = data.get('views')
            role_type = data.get('roleType')
            person_name = data.get('personName')
            password = data.get('password')
            flag = False
            if views is not None and isinstance(views, str):
                user.views = views
                flag = True
            if role_type is not None and isinstance(role_type, int):
                user.role_type = role_type
                flag = True
            if person_name is not None and isinstance(person_name, str):
                user.person_name = person_name
                flag = True
            if password is not None and isinstance(password, str):
                salted_password = str(hashlib.pbkdf2_hmac(
                    'sha512', password.encode('utf-8'), user.salt.encode('utf-8'), 100000).hex())
                user.salted_password = salted_password
                flag = True
            if flag:
                session.commit()
            return True, "succeed to update the User"
        except Exception as e:
            return False, str(e)
        finally:
            session.close()
